/**
 * @author Alexander Zerr
 * @version 1.3
 * @created 26.08.08
 */

(function() {

	var jYoup = window.jYoup = function(args) {
	
		this._id = 'jyoup';
		
		this._playList = [];
		this._lastState = -1;
		this._currVideo = 0;
		this._repeatState = -1; // 0:nothing,1:one,2:list
		this._showTimer = null;
		this._updateTimer = null;
		
		this.showedElm = 0;
		this.leftElm = 0;
		
		this._fsWin = null;
		this._parent = null;
		
		this._base = null;
		this._player = null; // swf player
		
		this._fullSize = 0;
		
		this._opt = {
			width:425,
			height:null,
			style:'red',
			layout:'default'			
		};
		
		this._elm = {
		 	bar:null,
		 	over:null,
		 	play:null,
		 	next:null,
		 	prev:null,
		 	mute:null,
		 	repeat:null,
		 	go:null,
		 	go_link:null,
		 	load_bar:null,
		 	loaded:null,
		 	played:null,
		 	time:null,
		 	play_line:null,
		 	fs:null
		};
			
		return (this instanceof jYoup ? 
			this.init.apply( this, args.callee ? args : arguments ) : new jYoup( arguments ));
	}
	
	jYoup.prototype = {
		
		init: function(o) {
			if(typeof o.playList != 'undefined') this.loadPlayList(o.playList);
			if(typeof o.fullSize != 'undefined') this._fullSize = o.fullSize;
			this.prepareOptions(o);
			this.prepareParent();			
			this.addHeadStyle();
			this.createPlayer();
			this.setSizes();		
			this.initEvents();
			this._player.jYoup = this;
			$_.addEvent(window, 'load',this.centerMenuBar.bind_scope(this));
		},
		
		prepareOptions: function(o) {			
			for(var i in this._opt) {
				if(typeof o[i] != 'undefined')	
					this._opt[i] = o[i];					
			}
		},
		
		prepareParent: function(o) {
			if(this._fullSize) {
				var p = opener.eListener.player[this._id +'_'+window.name.replace(/^.*_/, '')];
				this._parent = p;
				this._currVideo = p._currVideo;
				window.onresize = this.setSizes.bind_scope(this);
				this.loadPlayList(p._playList);
				this.prepareOptions(p._opt);
			};
			this._id += '_' + $_.time();
		},
		
		createPlayer: function() {
			var swfUrl = 'http://www.youtube.com/apiplayer?enablejsapi=1&fmt=18&playerapiid=' + this._id;

			document.write('<div id="'+ this._id +'" class="jyp_player">'
					+'<object id="player_' + this._id + '" data="'+swfUrl+'" type="application/x-shockwave-flash">'
					+'<param name="allowScriptAccess" value="always"/>'
					+'<param name="movie" value="'+swfUrl+'"></object>' 
					
					+ '<ul id="bar_' + this._id + '" class="jyp_bar">'
					+ 	'<li id="prev_' + this._id + '" class="jyp_prev" title="Previous Video"></li>'
					+ 	'<li id="play_' + this._id + '" class="jyp_play" title="Play/Pause"></li>'
					+ 	'<li id="next_' + this._id + '" class="jyp_next" title="Next Video"></li>'
					+ 	'<li id="repeat_' + this._id + '" title="Repeat/one/all"></li>'
					+	'<li id="load_bar_' + this._id + '" class="jyp_load_bar">'
					+ 		'<div id="play_line_' + this._id + '" class="jyp_lb_m"><div id="loaded_' + this._id + '" class="jyp_lb_l"></div><div id="played_' + this._id + '" class="jyp_lb_p"></div><div id="time_' + this._id + '" class="jyp_lb_t"></div></div>'
					+	'</li>'
					+ 	'<li id="go_' + this._id + '" class="jyp_go" title="Go to Source"><a id="go_link_' + this._id + '" target="_blank"></a></li>'
					+ 	'<li id="fs_' + this._id + '" class="jyp_max" title="Fullsize"></li>'
					+ 	'<li id="mute_' + this._id + '" class="jyp_mute" title="Mute/Umute"></li>'
					+ '</ul>'
					+'</div>');
			this._base = $_.elm(this._id);
			this._player = $_.elm('player_'+this._id);			
			for(var i in this._elm) this._elm[i] = $_.elm(i + '_' + this._id);
		},
		
		addHeadStyle: function() {
			$_.addCss('/jyoup/' + this._opt.layout + '/layout.css');
			$_.addCss('/jyoup/' + this._opt.layout + '/' + this._opt.style + '/style.css');
			if($_.isIe())
				$_.addCss('/jyoup/' + this._opt.layout + '/' + this._opt.style + '/ie_style.css');
		},
		
		setSizes: function() {
			if(this._fullSize) {				
				this._opt.width = document.body.offsetWidth;
				this._opt.height = document.body.offsetHeight-this._parent._elm.bar.offsetHeight;
				this.centerMenuBar();
			}
			this._opt.height = this._opt.height === null ? (this._opt.width/(4/3)) : this._opt.height;			
			$_.size(this._player,this._opt.width,this._opt.height);
			$_.size(this._base,this._opt.width);
		},
		
		centerMenuBar: function() {			
			var pl = (this._playList.length > 1) ? this._elm.play.offsetLeft : this._elm.repeat.offsetLeft; 
			var m = pl - this._elm.play.offsetWidth;
			var w = (this._opt.width - ((this.showedElm*this._elm.play.offsetWidth)+m*this.showedElm))+m;
			$_.size(this._elm.load_bar,w);
			$_.show(this._elm.load_bar);
        },		
		
		initEvents: function() {			
			$_.show(this._elm.play).onclick = this.playOnState.bind_scope(this);			
			
			$_.show(this._elm.repeat).onclick = this.repeatSwitch.bind_scope(this);
			$_.show(this._elm.go);
			$_.show(this._elm.mute).onclick = this.mute.bind_scope(this);
			this.showedElm = 4;
			this.leftElm = 2;	
			if(!$_.isIe()) {// hide if ie because ie go die i dont know why
				$_.show(this._elm.fs).onclick = this.switchFullSize.bind_scope(this);
				this.showedElm++;
				this.leftElm++;
			}			
			
			if(this._playList.length > 1) {
				$_.show(this._elm.next).onclick = this.nextVideo.bind_scope(this);
				$_.show(this._elm.prev).onclick = this.prevVideo.bind_scope(this);
				this.showedElm +=2;
				this.leftElm += 2;
			}
			if(this._fullSize)
				$_.css('set',this._elm.fs,'jyp_min');
			
			this._elm.load_bar.onmousedown=this.mouseDown.bind_scope(this);
		},
		setVolume: function (newVolume) {
        	this._player.setVolume(newVolume);
        },

        getVolume: function() {
        	return this._player.getVolume();
        },
		getPlayerState: function() {
        	return this._player.getPlayerState();
        },
		// Start Button Events -------------------------------------------------------
		playOnState: function() {
			switch(this.getPlayerState()) {
				case 2:
				case 5:
				case 0:
					this.play();
					break;
				case 1:
					this.pause();
					break;
			}
        },
        
        play: function() {
			this._player.playVideo();
		},
		
		playSwitch: function(cmd) {
			switch(cmd) {
				case 'play':
					$_.css('set',this._elm.play,'jyp_play');
					break;
				case 'pause':
					this.updatePlayer();
					$_.css('set',this._elm.play,'jyp_pause');
					break;
			}
		},
		
		pause: function() {
        	this._player.pauseVideo();
        },
        
        nextVideo: function() {    
        	this._currVideo = (++this._currVideo == this._playList.length) ? 0 : this._currVideo;
        	
        	if(this._lastState == 1)
				this.loadVideo();
			else
				this.cueVideo();
			
			this.updatePlayer();
        },
        
        prevVideo: function() {
        	this._currVideo = (--this._currVideo < 0) ? (this._playList.length-1) : this._currVideo;
        	if(this._lastState == 1)
				this.loadVideo();
			else
				this.cueVideo();
				
			this.updatePlayer();
        },
		
		cueVideo: function() {
        	this._player.cueVideoById(this._playList[this._currVideo], 0);
        },
        
        loadVideo: function () {
            this._player.loadVideoById(this._playList[this._currVideo], 0);          
        },
        
        mute: function() {
        	vol = this.getVolume();
        	switch(vol) {
        		case 0:
        			this.setVolume(100);
        			this.muteSwitch('unmute');
        		break;
        		case 100:
        			this.setVolume(0);
        			this.muteSwitch('mute');
        		break;
        	}
        },
        
        muteOnState: function() {
        	switch(this.getVolume()) {
        		case 0: return this.muteSwitch('mute');
        		case 100: return this.muteSwitch('unmute');
        	}
        },
        
        muteSwitch: function(state) {
        	switch(state) {
        		case 'mute':
        			$_.css('set',this._elm.mute,'jyp_unmute');
        			break;       		
        		case 'unmute':
        			$_.css('set',this._elm.mute,'jyp_mute');
        			break;
        	}
        },
        
        switchFullSize:function() {
        	switch(this._fullSize) {
        		case 1:
        			self.close();
        			break;
        		case 0:
        			this._fsWin = window.open("/jyoup/fullsize.html", "fullsize"+this._id, 'width='+screen.availWidth+',height='+screen.availHeight+',resizeable=yes,screenX=0,screenY=0');
        			this.pause();
        	}
        },
                
        repeatSwitch: function() {		
			switch(this._repeatState) {
				case -1:
				case 2:
					$_.css('set',this._elm.repeat,'jyp_repeat');
        			this._repeatState = 0;
					break;				
				case 0:
        			$_.css('set',this._elm.repeat,'jyp_repeat_one');
        			this._repeatState = 2//(this._playList.length>1) ? 1 : 2;
        			break;
				case 1:
        			$_.css('set',this._elm.repeat,'jyp_repeat_all');
        			this._repeatState = 2;
        			break;
			}
		},
		
		repeat: function() {
			if(this._repeatState <=0) return;
			
			switch(this._repeatState) {
				case 1:
					if(this.getPlayerState() == 0 && this._lastState == 1)
						this.play();
					if(this.getPlayerState() == 0 && this._lastState == 0)
						this.play();
					break;
				
			}
			/*switch(this.getPlayerState()) {
				case 0:
					if(this._repeatState == 1 && this._lastState == 3)
						this.play();
					
					/*
					else if(this._repeatState == 2) {
						this.nextVideo();
						//this.play();
					}
					break;		
			}*/
        },
		
		getVideoUrl: function() {
        	return this._player.getVideoUrl();
        },        
        
        loadPlayList: function(list) {
			if(typeof list == 'string') {
				
				if(list.indexOf(','))
					this._playList = this._playList.concat(list.split(','));
				else
					this._playList.push(list);
					
			}
			if(typeof list == 'array' || typeof list == 'object')
				this._playList = list;
			return this;
		},
		
		setLink: function() {
        	this._elm.go_link.href = this.getVideoUrl();
        },
        // End Button Events -------------------------------------------------------
		
		playerReady: function() {
			this._player.addEventListener("onStateChange", "eListener.onState." + this._id);
			this._player.addEventListener("onError", "eListener.onError." + this._id);			

			this.repeatSwitch();
			this.muteOnState();
			this.cueVideo();
			this.updatePlayer();
		},
		
		onState: function(state) {		
			//document.getElementById('dump').innerHTML += state +':'+this._lastState+'<br>';
			switch(state) {
				case 1:
					this.playSwitch('pause');
					break;
				case 2:
				case 5:
				case 0:
					this.playSwitch('play');
					if(state == 5) this.setLink();
					this.repeat();
			}
			this._lastState = state;
			//if(this._repeatState == 2 && state == 0) this.play();
		},
		
		onError: function() {},
		
		updatePlayer: function() {			
			this.setLoadedSize();
			this.setPlayedSize();
			if(this.getPlayerState() === 1)
				setTimeout(this.updatePlayer.bind_scope(this), 250);
		},
		
		setLoadedSize: function() {
			var pl = (this.getBt()<0) ? 0 :Math.round(((this.getSb() + this.getBl()) / this.getBt()) * 100);
			$_.sizeP(this._elm.loaded,pl);
		},
		
		setPlayedSize: function() {
			var pl = (this.getDu() < 1) ? 0 : Math.ceil((this.getCt() / this.getDu()) * 100);
			$_.sizeP(this._elm.played,pl);
			var pc = this._playList.length < 2 ? '' : (this._currVideo+1)+'-'+this._playList.length+' : '; 
			this._elm.time.innerHTML = pc + $_.toTime(this.getCt())+'/'+$_.toTime(this.getDu())+'&nbsp;';
		},
		
		getBl: function() {
        	return this._player.getVideoBytesLoaded();
        },
        
        getBt: function() {
        	return this._player.getVideoBytesTotal();
        },
        
        getCt: function() {
        	return this._player.getCurrentTime();
        },
        
        getDu: function() {
        	return this._player.getDuration();
        },
        
        getSb: function() {
        	return this._player.getVideoStartBytes();
        },
		
		mouseDown: function(e) {
			var evt = e || window.event;
			var elm = evt.target || evt.srcElement;
			var wp = Math.round(((evt.offsetX || evt.layerX) / this._elm.play_line.offsetWidth) * 100);
			var sec = (this.getDu() / 100) * wp;
            this._player.seekTo(sec, true);
		}
	}
	
	var $_ = {
		ls:[], // loadet style links
	
		elm: function(id) {
			return document.getElementById(id) || null;
		},
		
		time: function() {
			return +new Date();
		},
		
		toTime: function(t) {
			t = Math.round(t);
			return (t < 60) ? '0.' + (t < 10 ? '0' + t : t) : (t / 60).toFixed(2);
		},
		
		show: function(obj) {
			obj.style.display = 'block';
			return obj;
		},
		
		hide: function(obj) {
			obj.style.display = 'none';
			return obj;
		},
		
		size: function(o,w,h) {
			if(typeof w != 'undefined') o.style.width = w +'px';
			if(typeof h != 'undefined') o.style.height = h +'px';
		},
		
		sizeP: function(o,w,h) {
			if(typeof w != 'undefined') o.style.width = w +'%';
			if(typeof h != 'undefined') o.style.height = w +'%';
		},
		
		isIe: function() {// ie < 7
			return (typeof event != 'undefined' && typeof opera == 'undefined' && typeof XMLHttpRequest == "undefined");			
		},
		
		css: function(cmd,obj,css1,css2) {
			switch (cmd){
			  case 'set':
			    obj.className = css1;
			  break;
			  case 'swap':
			    obj.className=!$_.css('check',obj,css1)?obj.className.replace(css2,css1) : obj.className.replace(css1,css2);
			  break;
			  case 'add':
			    if(!$_.css('check',obj,css1)){obj.className+=obj.className?' '+css1:css1;}
			  break;
			  case 'remove':
			    var rep=obj.className.match(' '+css1)?' '+css1:css1;
			    obj.className=obj.className.replace(rep,'');
			  break;
			  case 'check':
			    return new RegExp('\\b'+css1+'\\b').test(obj.className);
			}		
		},
		
		addCss: function(css) {
			if(this.ls[css] === 1) return; // only one link per css
			var link=document.createElement("link");
			link.setAttribute("rel", "stylesheet")
			link.setAttribute("type", "text/css")
			link.setAttribute("href", css);
			document.getElementsByTagName('head')[0].appendChild(link);
			this.ls[css] = 1;
		},
		
		getStyle: function(o, css){
			if(document.defaultView && document.defaultView.getComputedStyle){
				return document.defaultView.getComputedStyle(o, "").getPropertyValue(css);
			}
			else if(o.currentStyle)	{
				css = css.replace(/\-(\w)/g, function (strMatch, p1){
					return p1.toUpperCase();
				});
				return o.currentStyle[css];
			}
		},
		
		addEvent: function(elm,evt,fn) {
			if (elm.addEventListener)
				elm.addEventListener(evt, fn, false);
			else if (elm.attachEvent)
				elm.attachEvent("on" + evt, fn);
		}
	}
	
	window.eListener = {
		onError: {},
		onState: {},
		player:{}
	};
	
	window.onYouTubePlayerReady = function(playerId) {
		var p = $_.elm('player_' + playerId).jYoup;
		p.playerReady();
		eListener.onState[p._id] = p.onState.bind_scope(p);
		eListener.onError[p._id] = p.onError.bind_scope(p);
		eListener.player[p._id] = p;
	}
	
	Function.prototype.bind_scope = function (object) {
		var m = this;
		var w = function () {
			var args = Array.prototype.slice.call(arguments);
			return m.apply(object, args);
		};
		return w;
	};
 
})();